﻿using System;
using System.Collections.Generic;
using HiComponents.IEvolution;

namespace ImageCom
{
    public class ImageCropPool : ObjectPool<IEImage>
    {
		#region Overrides of ObjectPool<ImageCropControl>
        protected override IEImage Create()
        {
            var ctrl = new IEImage();
			return ctrl;
		}
		
		#endregion

        

        public override bool Validate(IEImage reusable)
        {
            //throw new NotImplementedException();
            return true;
        }

        public override void Expire(IEImage reusable)
        {
           // throw new NotImplementedException();
            
        }
    }
	public class IEImagePool : ObjectPool<IEImage> {
		#region Overrides of ObjectPool<IEImage>
		protected override IEImage Create() {
			return new IEImage();
		}
		public override bool Validate(IEImage reusable) {
			return true;
		}
		public override void Expire(IEImage reusable) {
		}
		#endregion
	}
	public abstract class ObjectPool<T> {
		TimeSpan _expirationTime;
		Dictionary<T, DateTime> _unlocked;
		Dictionary<T, DateTime> _locked;
		readonly object _sync = new object();
		public ObjectPool() {
			_expirationTime = TimeSpan.FromSeconds(3);
			_locked = new Dictionary<T, DateTime>();
			_unlocked = new Dictionary<T, DateTime>();
		}
		public ObjectPool(TimeSpan expirationTime) : this() {
			_expirationTime = expirationTime;
		}
		protected abstract T Create();
		public abstract bool Validate(T reusable);
		public abstract void Expire(T reusable);
		public T CheckOut(Action<T> init=null) {
			lock (_sync) {
				T reusable = default(T);

				if (_unlocked.Count > 0) {
					foreach (KeyValuePair<T, DateTime> item in _unlocked) {
						if ((DateTime.UtcNow - item.Value) > _expirationTime) {
							// object has expired
							_unlocked.Remove(item.Key);
							Expire(item.Key);
						}
						else {
							if (Validate(item.Key)) {
								// find a reusable object
								_unlocked.Remove(item.Key);
								_locked.Add(item.Key, DateTime.UtcNow);
								reusable = item.Key;
								break;
							}
							else {
								// object failed validation
								_unlocked.Remove(item.Key);
								Expire(item.Key);
							}
						}
					}
				}

				// no object available, create a new one
				if (reusable == null) {
					reusable = Create();
					if (init != null) {
						init(reusable);
					}
					_locked.Add(reusable, DateTime.UtcNow);
				}

				return reusable;
			}
		}
		public void CheckIn(T reusable) {
			lock (_sync) {
				_locked.Remove(reusable);
				_unlocked.Add(reusable, DateTime.UtcNow);
			}
		}
	}

    public class Obj
    {
    }
}
